<template>
  <div class='wf-options'>
    <label v-if="showtitle"><div>{{ $t(playerinput.title) }}</div></label>
    <label v-if="playerinput.warning !== undefined" class="card-warning"><div>({{ $t(playerinput.warning) }})</div></label>
    <div v-for="(option, idx) in displayedOptions" :key="idx">
      <label class="form-radio" ref="optionLabels">
        <input v-model="selectedOption" type="radio" :name="radioElementName" :value="option" />
        <i class="form-icon" />
        <span>{{ $t(option.title) }}</span>
      </label>
      <div v-if="selectedOption === option" style="margin-left: 30px">
        <player-input-factory ref="inputfactory"
                              :players="players"
                              :playerView="playerView"
                              :playerinput="option"
                              :onsave="playerFactorySaved()"
                              :showsave="false"
                              :showtitle="false" />
      </div>
    </div>
    <div v-if="showsave && selectedOption">
      <div style="margin: 5px 30px 10px" class="wf-action">
        <AppButton :title="$t(selectedOption.buttonLabel)" type="submit" size="normal" @click="saveData" />
      </div>
    </div>
  </div>
</template>

<script lang="ts">

import Vue from 'vue';
import AppButton from '@/client/components/common/AppButton.vue';
import {isHTMLElement} from '@/client/utils/vueUtils';
import {PlayerViewModel, PublicPlayerModel} from '@/common/models/PlayerModel';
import {OrOptionsModel, PlayerInputModel} from '@/common/models/PlayerInputModel';
import {getPreferences} from '@/client/utils/PreferencesManager';
import {InputResponse, OrOptionsResponse} from '@/common/inputs/InputResponse';

let unique = 0;

export default Vue.extend({
  name: 'or-options',
  props: {
    playerView: {
      type: Object as () => PlayerViewModel,
    },
    players: {
      type: Array as () => Array<PublicPlayerModel>,
    },
    playerinput: {
      type: Object as () => OrOptionsModel,
    },
    onsave: {
      type: Function as unknown as () => (out: OrOptionsResponse) => void,
    },
    showsave: {
      type: Boolean,
    },
    showtitle: {
      type: Boolean,
    },
  },
  components: {
    AppButton,
  },
  data() {
    const displayedOptions = this.playerinput.options.filter((option) => {
      if (option.type !== 'card') {
        return true;
      }
      if (option.showOnlyInLearnerMode === false) {
        return true;
      }

      return getPreferences().learner_mode;
    });
    const initialIdx = this.playerinput.initialIdx ?? 0;
    // Special case: If the first recommended displayed option is SelectCard, and none of them are enabled, skip it.
    let selectedOption = displayedOptions[initialIdx];
    if (displayedOptions.length > 1 &&
      selectedOption.type === 'card' &&
      !selectedOption.cards.some((card) => card.isDisabled !== true)) {
      selectedOption = displayedOptions[initialIdx + 1];
    }
    return {
      displayedOptions,
      radioElementName: 'selectOption' + unique++,
      selectedOption,
    };
  },
  watch: {
    selectedOption(newOption: PlayerInputModel) {
      // Clicking the option can shift elements on the page.
      // This preserves the location of the option button the user just clicked by
      // tracking where it was on the screen, where it moved, and then repositioning it.
      const anchorTop = this.getTop(newOption);
      this.$nextTick(() => {
        const newTop = this.getTop(newOption);
        if (anchorTop !== undefined && newTop !== undefined) {
          const delta = newTop - anchorTop;
          if (Math.abs(delta) > 0.5) {
            window.scrollBy(0, delta);
          }
        }
      });
    },
  },
  methods: {
    getTop(option: PlayerInputModel | undefined): number | undefined {
      if (option === undefined) {
        return undefined;
      }
      const element = this.getOptionLabelElement(option);
      return element?.getBoundingClientRect().top;
    },
    getOptionLabelElement(option: PlayerInputModel): HTMLElement | undefined {
      const idx = this.displayedOptions.indexOf(option);
      const refs = this.$refs.optionLabels;
      if (idx === -1 || !refs) {
        return undefined;
      }

      const val = Array.isArray(refs) ? refs[idx] : refs;
      return isHTMLElement(val) ? val : undefined;
    },
    playerFactorySaved() {
      const idx = this.playerinput.options.indexOf(this.selectedOption);
      if (idx === undefined || idx === -1) {
        throw new Error('option not found');
      }
      return (out: InputResponse) => {
        this.onsave({
          type: 'or',
          index: idx,
          response: out,
        });
      };
    },
    saveData() {
      let ref = this.$refs['inputfactory'];
      if (Array.isArray(ref)) {
        ref = ref[0];
      }
      (ref as any).saveData();
    },
  },
});

</script>

